package org.saber.geo.utils;

import java.util.ArrayList;
import java.util.List;

import org.saber.geo.model.Line;
import org.saber.geo.model.Point;

/**
 * 平面坐标系工具
 * 
 * @author saber
 *
 */
public class PlaneCoordinateUtils {

	/**
	 * 求三坐标点角度
	 * 
	 * @param pointx
	 * @param pointy
	 * @return
	 */
	public static double getAngleByThreeP(double[] pointx, double[] pointy)

	{
		double a_b_x = pointx[0] - pointx[1];

		double a_b_y = pointy[0] - pointy[1];

		double c_b_x = pointx[2] - pointx[1];

		double c_b_y = pointy[2] - pointy[1];

		double ab_mul_cb = a_b_x * c_b_x + a_b_y * c_b_y;

		double dist_ab = Math.sqrt(a_b_x * a_b_x + a_b_y * a_b_y);

		double dist_cd = Math.sqrt(c_b_x * c_b_x + c_b_y * c_b_y);

		double cosValue = ab_mul_cb / (dist_ab * dist_cd);

		return Math.acos(cosValue);

	}

	/**
	 * 获取不规则多边形重心点
	 * 
	 * @param mPoints
	 * @return
	 */
	public static Point getCenterOfGravityPoint(List<Point> mPoints) {
		double area = 0.0;// 多边形面积
		double Gx = 0.0, Gy = 0.0;// 重心的x、y
		for (int i = 1; i <= mPoints.size(); i++) {
			double iLat = mPoints.get(i % mPoints.size()).getY();
			double iLng = mPoints.get(i % mPoints.size()).getX();
			double nextLat = mPoints.get(i - 1).getY();
			double nextLng = mPoints.get(i - 1).getX();
			double temp = (iLat * nextLng - iLng * nextLat) / 2.0;
			area += temp;
			Gy += temp * (iLat + nextLat) / 3.0;
			Gx += temp * (iLng + nextLng) / 3.0;
		}
		Gx = Gx / area;
		Gy = Gy / area;
		return new Point(Gx, Gy);
	}

	/**
	 * 检测坐标点在基准点 相对位置
	 * 
	 * @param basePoint
	 * @param oriPoint
	 * @return 1:左侧 -1 正上 2 右侧 -2正下 0 相交
	 */
	public static Location checkLocation(Point basePoint, Point oriPoint) {
		if (oriPoint.getX() > basePoint.getX()) {
			if (oriPoint.getY() == basePoint.getY())
				return Location.RIGHT;
			if (oriPoint.getY() > basePoint.getY())
				return Location.TOPRIGHT;
			return Location.LOWERRIGHT;
		}
		if (oriPoint.getX() == basePoint.getX()) {
			if (oriPoint.getY() > basePoint.getY()) {
				return Location.TOP;
			}
			if (oriPoint.getY() == basePoint.getY())
				return Location.CENTER;
			return Location.BELOW;
		}
		if (oriPoint.getX() < basePoint.getX()) {
			if (oriPoint.getY() > basePoint.getY()) {
				return Location.TOPLEFT;
			}
			if (oriPoint.getY() == basePoint.getY())
				return Location.LEFT;
			return Location.LOWERLEFT;
		}
		return null;

	}

	/**
	 * 获取一条线段
	 * 
	 * @param pointA
	 * @param pointB
	 * @return
	 */
	public static Line getLine(Point pointA, Point pointB) {
		double distance = getDistance(pointA, pointB);
		Line line = new Line();

		line.setBasePoint(pointA);
		line.setPointB(pointB);

		line.setLength(distance);
		line.setK(getK(pointA, pointB));
		return line;
	}

	/**
	 * 获取两点距离
	 * 
	 * @param pointA
	 * @param pointB
	 * @return
	 */
	public static double getDistance(Point pointA, Point pointB) {
		double x1 = pointA.getX();
		double y1 = pointA.getY();

		double x2 = pointB.getX();
		double y2 = pointB.getY();

		Double distance = Math.pow((Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2)), 0.5);
		return distance;
	}

	/**
	 * 获取斜率
	 * 
	 * @param pointA
	 * @param pointB
	 * @return
	 */
	public static double getK(Point pointA, Point pointB) {
		double x1 = pointA.getX();
		double y1 = pointA.getY();

		double x2 = pointB.getX();
		double y2 = pointB.getY();

		double k = (y2 - y1) / (x2 - x1);
		return k;
	}

	/**
	 * 根据相关信息，获取该点坐标
	 * 
	 * @param basePoint 基准点
	 * @param distance  与基准点距离
	 * @param k         斜率
	 * @param location  与基准点相对位置
	 * @return 该点坐标
	 */
	public static Point getPoint(Point basePoint, double distance, double k, Location location) {

		Point oriPoint = basePoint;
		double length = distance;
		double x1 = oriPoint.getX();
		double y1 = oriPoint.getY();

		double x2 = 0;
		double y2 = 0;

		double bb = -k * x1 + y1;
		y2 = k * x2 + bb;
//
//		double x=x1-x2;
//		double y=y1-y2;
		final double a = k * k + 1;
		final double b = -2 * x1 - 2 * k * k * x1;
		final double c = x1 * x1 + k * k * x1 * x1 - length * length;
		double[] xResults = MathUtils.getSqrt(a, b, c);

		switch (location) {
		case LEFT:
		case TOP:
		case TOPLEFT:
		case CENTER:
		case LOWERLEFT:
		case BELOW:
			x2 = xResults[1];
			break;
		case RIGHT:
		case TOPRIGHT:
		case LOWERRIGHT:
			x2 = xResults[0]; // 取x大值
		default:
			break;
		}

		y2 = k * x2 + bb;
		Point newPoint = new Point(x2, y2);

		return newPoint;
	}

	public static double pointToLine(Point point1, Point point2, Point point0) {
		double space = 0;

		double a, b, c;

		a = getDistance(point1, point2);// 线段的长度

		b = getDistance(point1, point0);// (x1,y1)到点的距离

		c = getDistance(point2, point0);// (x2,y2)到点的距离

		if (c <= 0.000001 || b <= 0.000001) {
			space = 0;
			return space;

		}
		if (a <= 0.000001) {
			space = b;
			return space;
		}
		if (c * c >= a * a + b * b) {
			space = b;
			return space;
		}
		if (b * b >= a * a + c * c) {
			space = c;
			return space;
		}

		double p = (a + b + c) / 2;// 半周长

		double s = Math.sqrt(p * (p - a) * (p - b) * (p - c));// 海伦公式求面积

		space = 2 * s / a;// 返回点到线的距离(利用三角形面积公式求高)

		return space;

	}

	/**
	 * 是否为同一坐标点
	 * @param pointA
	 * @param pointB
	 * @return
	 */
	public static boolean isSamePoint(Point pointA , Point pointB) {
		if(pointA.getX()==pointB.getX()&&pointA.getY()==pointB.getY())
			return true;
		return false;
	}
	
	/**
	 * 是否为多边形
	 * @param points
	 * @return true 多边形 false 折线
	 */
	public static boolean isPolygon(List<Point> points) {
		
		if(points.size()<2)
			return false;

		Point sPoint=points.get(0);
		Point ePoint=points.get(points.size()-1);
		
		return isSamePoint(sPoint, ePoint);
	}
	
	
	/**
	 * 折线变形为多边形 （极微小变换）
	 * @param points
	 * @return
	 */
	public static List<Point> line2Polygon(List<Point> points){
		List<Point> polygonPoints=new ArrayList<Point>();
		return polygonPoints;
	}
	
}
